﻿
namespace Apache.Cassandra.Client.Diagnostics {
    using System.Diagnostics;

    sealed internal class CassandraClientPoolCounters {

        private static class CreationData {
            internal const string CategoryName = "NetCassa Client Pools";
            internal const string CategoryHelp = "Counters for Apache.Cassandra.Client";

            static internal readonly CounterCreationData NumberOfActiveEndPointPools = new CounterCreationData("End Point Pools Active", "Number of active end point pools.", PerformanceCounterType.NumberOfItems32);
            static internal readonly CounterCreationData NumberOfInactiveEndPointPools = new CounterCreationData("End Point Pools Inactive", "Number of inactive end point pools.", PerformanceCounterType.NumberOfItems32);

            static internal readonly CounterCreationData NumberOfPooledConnections = new CounterCreationData("Connections Pooled", "Number of connections managed by the pool.", PerformanceCounterType.NumberOfItems32);
            static internal readonly CounterCreationData NumberOfFreeConnections = new CounterCreationData("Connections Free", "Number of available connections in the pool.", PerformanceCounterType.NumberOfItems32);
            static internal readonly CounterCreationData NumberOfStasisConnections = new CounterCreationData("Connections in Statis", "Number of connections waiting to be made available.", PerformanceCounterType.NumberOfItems32);
            static internal readonly CounterCreationData NumberOfReclaimedConnections = new CounterCreationData("Connections Reclaimed", "Number of connections reclaimed by garbage collection.", PerformanceCounterType.NumberOfItems32);

            static internal readonly CounterCreationData HardConnectsPerSecond = new CounterCreationData("Hard Connects per Second", "Number of actual cluster client connections opened per second.", PerformanceCounterType.RateOfCountsPerSecond32);
            static internal readonly CounterCreationData SoftConnectsPerSecond = new CounterCreationData("Soft Connects per Second", "Number of clients retrived from the pool per second.", PerformanceCounterType.RateOfCountsPerSecond32);
            static internal readonly CounterCreationData SoftDisconnectsPerSecond = new CounterCreationData("Soft Disconnects per Second", "Number of clients returned to the pool per second.", PerformanceCounterType.RateOfCountsPerSecond32);
            static internal readonly CounterCreationData HardDisconnectsPerSecond = new CounterCreationData("Hard Disconnects per Second", "Number of actual cluster client connections closed per second.", PerformanceCounterType.RateOfCountsPerSecond32);
        }

        internal readonly CassandraCounter NumberOfActiveEndPointPools;
        internal readonly CassandraCounter NumberOfInactiveEndPointPools;

        internal readonly CassandraCounter NumberOfPooledConnections;
        internal readonly CassandraCounter NumberOfFreeConnections;
        internal readonly CassandraCounter NumberOfStasisConnections;
        internal readonly CassandraCounter NumberOfReclaimedConnections;

        internal readonly CassandraCounter HardConnectsPerSecond;
        internal readonly CassandraCounter SoftConnectsPerSecond;
        internal readonly CassandraCounter SoftDisconnectsPerSecond;
        internal readonly CassandraCounter HardDisconnectsPerSecond;

        internal CassandraClientPoolCounters(string instanceName) {
            NumberOfActiveEndPointPools = new CassandraCounter(CreationData.CategoryName, instanceName, CreationData.NumberOfActiveEndPointPools);
            NumberOfInactiveEndPointPools = new CassandraCounter(CreationData.CategoryName, instanceName, CreationData.NumberOfInactiveEndPointPools);
            
            NumberOfPooledConnections = new CassandraCounter(CreationData.CategoryName, instanceName, CreationData.NumberOfPooledConnections);
            NumberOfFreeConnections = new CassandraCounter(CreationData.CategoryName, instanceName, CreationData.NumberOfFreeConnections);
            NumberOfStasisConnections = new CassandraCounter(CreationData.CategoryName, instanceName, CreationData.NumberOfStasisConnections);
            NumberOfReclaimedConnections = new CassandraCounter(CreationData.CategoryName, instanceName, CreationData.NumberOfReclaimedConnections);
            
            HardConnectsPerSecond = new CassandraCounter(CreationData.CategoryName, instanceName, CreationData.HardConnectsPerSecond);
            SoftConnectsPerSecond = new CassandraCounter(CreationData.CategoryName, instanceName, CreationData.SoftConnectsPerSecond);
            SoftDisconnectsPerSecond = new CassandraCounter(CreationData.CategoryName, instanceName, CreationData.SoftDisconnectsPerSecond);
            HardDisconnectsPerSecond = new CassandraCounter(CreationData.CategoryName, instanceName, CreationData.HardDisconnectsPerSecond);
        }

        static internal void InstallCounters() {
            CounterCreationDataCollection counterData = new CounterCreationDataCollection();

            counterData.Add(CreationData.NumberOfActiveEndPointPools);
            counterData.Add(CreationData.NumberOfInactiveEndPointPools);
            
            counterData.Add(CreationData.NumberOfPooledConnections);
            counterData.Add(CreationData.NumberOfFreeConnections);
            counterData.Add(CreationData.NumberOfStasisConnections);
            counterData.Add(CreationData.NumberOfReclaimedConnections);
            
            counterData.Add(CreationData.HardConnectsPerSecond);
            counterData.Add(CreationData.SoftConnectsPerSecond);
            counterData.Add(CreationData.SoftDisconnectsPerSecond);
            counterData.Add(CreationData.HardDisconnectsPerSecond);

            PerformanceCounterCategory.Create(CreationData.CategoryName, CreationData.CategoryHelp, PerformanceCounterCategoryType.MultiInstance, counterData);
        }

        static internal void UninstallCounters() {
            if (PerformanceCounterCategory.Exists(CreationData.CategoryName)) {
                PerformanceCounterCategory.Delete(CreationData.CategoryName);
            }
        }
    }
}
